package com.jielihaofeng.nettyadvance.rpc.server.handler;

import com.jielihaofeng.nettyadvance.rpc.message.RpcRequestMessage;
import com.jielihaofeng.nettyadvance.rpc.message.RpcResponseMessage;
import com.jielihaofeng.nettyadvance.rpc.server.service.HelloService;
import com.jielihaofeng.nettyadvance.rpc.server.service.ServiceFactory;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;

/**
 * @author Johnnie Wind
 * @description RPC请求消息处理器
 * @date 2021/11/19 14:44
 */
@Slf4j
@ChannelHandler.Sharable
public class RpcRequestMessageHandler extends SimpleChannelInboundHandler<RpcRequestMessage> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequestMessage msg) {

        // 返回响应对象
        RpcResponseMessage response = new RpcResponseMessage();

        // 请求序号
        int sequenceId = msg.getSequenceId();
        response.setSequenceId(sequenceId);

        // 接口名
        String interfaceName = msg.getInterfaceName();
        // 方法名
        String methodName = msg.getMethodName();
        // 返回值类型
        Class<?> returnType = msg.getReturnType();
        // 参数类型
        Class[] parameterTypes = msg.getParameterTypes();
        // 参数值
        Object[] parameterValue = msg.getParameterValue();

        try {
            // 获取服务
            HelloService service = (HelloService) ServiceFactory.getService(Class.forName(interfaceName));
            // 获取对应方法
            Method method = service.getClass().getMethod(methodName, parameterTypes);
            // 调用方法
            Object invoke = method.invoke(service, parameterValue);
            // 设置返回值
            response.setReturnValue(invoke);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("服务调用异常", e);
            // 设置异常
            response.setExceptionValue(new RuntimeException("远程调用出错：" + e.getCause().getMessage()));
        }
        // 返回响应结果
        ctx.writeAndFlush(response);
    }
}
